﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IrisMembership.DomainClasses;
using System.Data.Entity;
using IrisMembership.DataLayer;

namespace IrisMembership.ServiceLayer
{
    public class PermissionService : IPermissionService
    {
        private readonly IDbSet<Permission> _permissions;
        private readonly IIrisDbContext _dbContext;
        private readonly IRoleService _roleService;
        public PermissionService(IIrisDbContext dbContext, IRoleService roleService)
        {
            _dbContext = dbContext;
            _permissions = _dbContext.Set<Permission>();
            _roleService = roleService;
        }

        public bool CanAccess(int userId, string controllerName, string actionName, string areaName)
        {
            //var result = db.Users.Single(u => u.UserName == userName).Roles.Any(r => r.ApplicationActions.Any(a => a.ControllerName == controllerName && a.ActionName == actionName && a.AreaName == areaName));

            controllerName = controllerName.ToLower();
            actionName = actionName.ToLower();
            areaName = areaName.ToLower();


            var canAccess =
                _permissions.Where(p => p.Roles.Any(r => r.Users.Any(u => u.Id == userId)))
                    .Any(p => p.ControllerName == controllerName && p.ActionName == actionName && p.AreaName == areaName);


            if (canAccess) return true;



            var userRoles = _roleService.GetUserRoles(userId);

            var userRolesList = new List<Role>();

            LoadTreeNode(userRoles, userRolesList);

            canAccess = userRolesList.Any(
                r =>
                    r.Permissions.Any(
                        a =>
                            a.ControllerName == controllerName && a.ActionName == actionName &&
                            a.AreaName == areaName));


            return canAccess;

            //var roles = db.Roles.Where(r => r.Users.Any(u => u.UserName == userName)).ToList();


            //var childRoles = new List<Role>();

            //loadTreeNode(roles, childRoles);


            //return childRoles.Any(z => z.ApplicationActions.Any(a => a.ControllerName == controllerName && a.ActionName == actionName && a.AreaName == areaName));
        }

        private static void LoadTreeNode(ICollection<Role> treeRoles, ICollection<Role> listRoles)
        {
            foreach (var roleNode in treeRoles)
            {
                //Trace.WriteLine(String.Format(node.Tag));
                listRoles.Add(roleNode);
                LoadTreeNode(roleNode.ChildrenRoles, listRoles);
            }
        }



        public IList<Permission> GetRolePermissions(int roleId)
        {
            return _permissions.Where(p => p.Roles.Any(r => r.Id == roleId)).ToList();
        }
    }
}
